package com.weibei.common.utils.jd;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @Author: jiameng@jd.com
 * @Date: 2020/7/24 10:29
 * @Description:
 */
public class RequestToBeanUtil {

    /**
     * 解决servlet中接收参数赋值给实体的赋值问题，采用此工具可以快速构建所需的bean
     *
     * @param clazz   java对象
     * @param request
     */
    public static <T> T requestToBean(Class<T> clazz, HttpServletRequest request) {
        T bean = null;
        //读取对象中的所有方法
        Method[] methods = clazz.getDeclaredMethods();
        String[] pattern = new String[]{"yyyy-MM", "yyyyMM", "yyyy/MM", "yyyyMMdd", "yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMddHHmmss", "yyyy-MM-dd HH:mm:ss"};
        try {
            //通过反射构建Bean
            bean = clazz.newInstance();
            //通过遍历对象方法查找出方法名
            for (Method method : methods) {
                String methodName = method.getName();
                //只需要匹配出set方法
                if (!StringUtils.isBlank(methodName) && methodName.startsWith("set")) {
                    //获取到set方法明后截取，获取字段名 setUserName ----> userName;
                    String field = methodName.toLowerCase().charAt(3) + methodName.substring(4, methodName.length());
                    String value = request.getParameter(field);
                    //如果参数值不存在 或者 不等于"" 跳出本次循环
                    if (StringUtils.isBlank(value)) {
                        continue;
                    }
                    //取得方法对应的数据类型
                    Object fieldType = method.getParameterTypes()[0];
                    //判断String类型
                    if (fieldType.equals(String.class)) {
                        method.invoke(bean, value);
                    } //判断Integer类型
                    else if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) {
                        method.invoke(bean, Integer.valueOf(value));
                    } //判断Long类型
                    else if (fieldType.equals(Long.class) || fieldType.equals(long.class)) {
                        method.invoke(bean, Long.valueOf(value));
                    } //判断Double类型
                    else if (fieldType.equals(Double.class) || fieldType.equals(double.class)) {
                        method.invoke(bean, Double.valueOf(value));
                    } //判断Float类型
                    else if (fieldType.equals(Float.class) || fieldType.equals(float.class)) {
                        method.invoke(bean, Float.valueOf(value));
                    } //判断Boolean类型
                    else if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) {
                        //由于有时候我们传递参数是通过0 和 1 来代替 true 和 false
                        //这里我们多一步转换,否则采用BooleanUtils工具类转换
                        if ("1".equals(value)) {
                            method.invoke(bean, true);
                        } else if ("0".equals(value)) {
                            method.invoke(bean, false);
                        } else {
                            method.invoke(bean, BooleanUtils.toBoolean(value));
                        }
                    } //判断BigDecimal类型
                    else if (fieldType.equals(BigDecimal.class)) {
                        method.invoke(bean, new BigDecimal(value));
                    } //判断Date类型
                    else if (fieldType.equals(Date.class)) {
                        //采用 apache 的 DateUtils 工具类转换Data
                        //pattern 为参数传递匹配的格式
                        method.invoke(bean, DateUtils.parseDate(value, pattern));
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return bean;
    }

}


